# coding: utf-8
# @Author: ChuiZi
import logging
from time import sleep

from selenium import webdriver
from selenium.common import WebDriverException
from selenium.webdriver.common.action_chains import ActionChains

from lib.common.baseFunc import callSelf


# 创建一个浏览器,默认为edge浏览器,需要安装驱动
def new_webdriver(webdriverType='edge', open_GUI=True):
    """
    开启指定浏览器
    :param webdriverType: 浏览器类型
    :param open_GUI: 是否开启GUI模式,默认开启
    :return:
    """
    webType = {
        "firefox": [webdriver.Firefox, webdriver.FirefoxOptions],
        "edge": [webdriver.Edge, webdriver.EdgeOptions],
        "chrmoe": [webdriver.Chrome, webdriver.ChromeOptions]
    }
    # 开关GUI模式,节约GPU
    if open_GUI:
        options = None
    else:
        options = callSelf(webType[webdriverType.lower()][1])
        options.add_argument('--headless')
        options.add_argument("--disable-gpu")
    # 创建对应浏览器实例,开启浏览器
    try:
        driver = callSelf(webType[webdriverType.lower()][0], options=options)
    except WebDriverException:
        raise f"未安装{webdriverType}对应的驱动,或者系统环境路径未配置"
    except Exception as err:
        raise err
    return driver


class Common_webdriver:
    def __init__(self, driver):
        self.driver = driver

    # 打开url
    def open(self, url):
        self.driver.get(url)

    # 关闭当前窗口,若只有一个窗口,则关闭浏览器
    def close(self):
        self.driver.close()

    # 关闭浏览器
    def quit(self):
        self.driver.quit()

    # 回退
    def back(self):
        self.driver.back()

    # 刷新
    def refresh(self, time):
        self.driver.refresh()
        sleep(time)

    # 元素定位-单个
    def locator(self, name, value):
        """
        :param name: 定位方法,通常有id,name,class,xpath等
        :param value: 定位数据
        :return: 元素内存地址
        """
        return self.driver.find_element(name, value)

    # 元素定位_封装提供给数据驱动使用
    def locator_list(self, lis):
        return self.locator(lis[0], lis[1])

    # 元素定位-多个
    def locators(self, name, value):
        return self.driver.find_elements(name, value)

    # 元素定位_封装提供给数据驱动使用
    def locators_list(self, lis):
        return self.locators(lis[0], lis[1])

    # 通过元素定位后进行点击
    def button(self, name, value):
        self.locator(name, value).click()

    # 批量点击
    def button_list(self, lis):
        self.button(lis[0], lis[1])

    # 点击某一个控件
    def button_ele(self, ele):
        """
        :param ele: 元素内存地址,需要通过元素定位找到对应控件
        """
        ele.click()

    # 鼠标悬停事件
    def hover(self, name, value):
        ActionChains(self.driver).move_to_element(self.locator(name, value)).perform()

    def hover_lis(self, lis):
        self.hover(lis[0], lis[1])

    # 元素定位,然后输入文本
    def input(self, name, value, txt):
        el = self.locator(name, value)
        el.clear()
        el.send_keys(txt)

    # 批量元素定位,然后输入文本对应
    def input_list(self, lis, txt=None):
        if txt is None:
            (name, value, txt, *arg) = lis
        else:
            (name, value, *arg) = lis
        self.input(name, value, txt)

    # 当前浏览器所有页签
    def windows_handles(self):
        return self.driver.window_handles

    # 切换页签
    def change_window(self, numb):
        self.driver.switch_to.window(self.windows_handles[numb])

    # 判断元素是否存在
    def isElementExist(self, name, value):
        """
        判断页面是否存在指定路径下的控件
        :param name:
        :param value:
        :return:
        """
        exist = True
        try:
            self.locator(name, value)
        except:
            exist = False
        finally:
            return exist

    # 批量判断元素是否存在
    def isElementExist_list(self, lis):
        (name, value, *arg) = lis
        return self.isElementExist(name, value)

    # 获取到对应控件下的所有子控件
    @classmethod
    def childrens_ele(cls, parent_ele, name, value):
        """ 获取到对应控件下的所有子控件
        :param parent_ele: 父控件
        :param name: 定位方法
        :param value: 定位依据
        :return:子节点列表
        """
        return parent_ele.find_elements(name, value)

    # 获取到对应控件下的所有子控件_提供给数据驱动使用
    @classmethod
    def childrens_ele_list(cls, parent_ele, lis):
        """
        # 获取到对应控件下的所有子控件
        :param parent_ele:
        :param lis:
        :return:子节点列表
        """
        (name, value, *arg) = lis
        return cls.childrens_ele(parent_ele, name, value)

    @classmethod
    def children_ele(cls, parent_ele, by_id, value):
        """
        # 获取到对应控件下的某个子控件
        :param parent_ele:
        :param by_id:
        :param value:
        :return:子节点
        """
        return parent_ele.find_element(by_id, value)

    @classmethod
    def children_ele_list(cls, parent_ele, lis):
        """
        # 获取到对应控件下的某个子控件
        :param parent_ele:
        :param lis:
        :return:子节点
        """
        return cls.children_ele(parent_ele, lis[0], lis[1])

    # 返回节点的文本信息
    def ele_text(self, ele):
        """返回节点的文本信息"""
        return self.locator_list(ele).text

    # 判断节点是否存在,返回布尔值
    def ele_exist(self, lis):
        """判断节点是否存在,返回布尔值"""
        (name, value, *arg) = lis
        try:
            self.driver.find_element(name, value)
            return True
        except:
            return False


if __name__ == "__main__":
    firfox_webdriver = Common_webdriver(new_webdriver())
    firfox_webdriver.open('http://www.baidu.com')
    sleep(2)
    firfox_webdriver.close()
